package com.wtf.dsp.admin.aspect;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.wtf.dsp.admin.filter.LogMdcFilter;
import com.wtf.dsp.admin.hanlder.GlobalExceptionHandler;
import com.wtf.dsp.admin.util.MdcUtil;
import com.wtf.dsp.core.api.R;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Author huangxiong
 * @Date 2019/6/13 0013
 **/
@Aspect
@Slf4j
@Component
public class RequestLogAspect implements Ordered {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Around(value = "within(com..*) " +
            "&& (@annotation(org.springframework.web.bind.annotation.RequestMapping)" +
            "|| @annotation(org.springframework.web.bind.annotation.GetMapping)" +
            "|| @annotation(org.springframework.web.bind.annotation.PostMapping))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String urlParams = request.getQueryString();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 定义返回对象、得到方法需要的参数
        Object apiResult = null;
        Object[] body = joinPoint.getArgs();
        try {
            apiResult = joinPoint.proceed(body);
        } finally {
            long endTime = System.currentTimeMillis();
            Map<String,Object> apiLog = new LinkedHashMap<>();
            apiLog.put("url_method",request.getMethod());
            apiLog.put("url",StringUtils.isEmpty(urlParams) ? request.getRequestURL() : request.getRequestURL() + "?" + urlParams);
            apiLog.put("queryParam",urlParams);
            apiLog.put("body",body);
            apiLog.put("status",joinPoint.getTarget() instanceof GlobalExceptionHandler ? "error" : "success" );
            apiLog.put("method", signature.getDeclaringTypeName() + "." + signature.getName());
            apiLog.put("return",apiResult);
            apiLog.put("startTime", DateUtil.format(new Date(startTime), DatePattern.NORM_DATETIME_MS_FORMAT));
            apiLog.put("endTime",DateUtil.format(new Date(endTime), DatePattern.NORM_DATETIME_MS_FORMAT));
            apiLog.put("cosTime", endTime  - startTime);
            log.info("【Api Request Log】 : {}", objectMapper.writeValueAsString(apiLog) );
        }
        if(apiResult instanceof R  && org.apache.commons.lang.StringUtils.isBlank(((R) apiResult).getRequestId())){
            R r = (R) apiResult;
            r.setRequestId(MdcUtil.getLogMid());
        }
        return apiResult;
    }


    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }
}
